
package com.gitee.flow.grpc;

import com.gitee.flow.FlowFactory;
import com.gitee.flow.FlowMapper;
import com.gitee.flow.entity.HiTaskinstEntity;
import com.gitee.flow.mapper.HiTaskinstMapper;
import com.gitee.flow.mapper.RuIdentitylinkMapper;
import com.gitee.flow.mapper.TaskAttachmentMapper;
import com.gitee.flow.service.FlowRead;
import com.gitee.flow.service.FlowWrite;
import com.gitee.flow.service.HiTaskinstRead;
import com.gitee.jmash.common.grpc.GrpcContext;
import com.gitee.jmash.common.utils.VersionUtil;
import com.gitee.jmash.core.grpc.cdi.GrpcService;
import com.gitee.jmash.core.jaxrs.ParamsValidationException;
import com.gitee.jmash.core.lib.ProtoEnumUtil;
import com.gitee.jmash.core.orm.DtoPageImpl;
import com.gitee.jmash.core.orm.DtoTotal;
import com.gitee.jmash.core.utils.FileServiceUtil;
import com.google.api.HttpBody;
import com.google.protobuf.Any;
import com.google.protobuf.BoolValue;
import com.google.protobuf.Empty;
import com.google.protobuf.EnumValue;
import com.google.protobuf.Int32Value;
import com.google.protobuf.StringValue;
import io.grpc.Status;
import io.grpc.stub.StreamObserver;
import java.util.List;
import java.util.Map;
import jmash.flow.protobuf.BusinessStatusReq;
import jmash.flow.protobuf.DeployKey;
import jmash.flow.protobuf.DeployReq;
import jmash.flow.protobuf.DeployRes;
import jmash.flow.protobuf.DeployXmlReq;
import jmash.flow.protobuf.HiCommentList;
import jmash.flow.protobuf.HiCommentModel;
import jmash.flow.protobuf.HiProcInstModel;
import jmash.flow.protobuf.HiProcInstPage;
import jmash.flow.protobuf.HiProcInstReq;
import jmash.flow.protobuf.HiProcinstKey;
import jmash.flow.protobuf.HiTaskinstKey;
import jmash.flow.protobuf.HiTaskinstList;
import jmash.flow.protobuf.HiTaskinstModel;
import jmash.flow.protobuf.HiTaskinstReq;
import jmash.flow.protobuf.IdentityLinkList;
import jmash.flow.protobuf.IdentityLinkModel;
import jmash.flow.protobuf.ProcDefKey;
import jmash.flow.protobuf.ProcDefList;
import jmash.flow.protobuf.ProcDefModel;
import jmash.flow.protobuf.ProcDefReq;
import jmash.flow.protobuf.ProcInstDeleteReq;
import jmash.flow.protobuf.ProcInstKey;
import jmash.flow.protobuf.ProcInstModel;
import jmash.flow.protobuf.ProcInstPage;
import jmash.flow.protobuf.ProcInstReq;
import jmash.flow.protobuf.ProcInstSuspendReq;
import jmash.flow.protobuf.ProcInstVars;
import jmash.flow.protobuf.StartProcInstReq;
import jmash.flow.protobuf.TaskAssignReq;
import jmash.flow.protobuf.TaskAttachmentCreateReq;
import jmash.flow.protobuf.TaskAttachmentKey;
import jmash.flow.protobuf.TaskAttachmentList;
import jmash.flow.protobuf.TaskAttachmentModel;
import jmash.flow.protobuf.TaskAttachmentReq;
import jmash.flow.protobuf.TaskAttachmentUpdateReq;
import jmash.flow.protobuf.TaskClaimReq;
import jmash.flow.protobuf.TaskDefList;
import jmash.flow.protobuf.TaskDelegateReq;
import jmash.flow.protobuf.TaskGobackReq;
import jmash.flow.protobuf.TaskHandleReq;
import jmash.flow.protobuf.TaskIdentityLinkReq;
import jmash.flow.protobuf.TaskKey;
import jmash.flow.protobuf.TaskModel;
import jmash.flow.protobuf.TaskPage;
import jmash.flow.protobuf.TaskPriorityReq;
import jmash.flow.protobuf.TaskReq;
import jmash.flow.protobuf.TaskResolveReq;
import jmash.flow.protobuf.TaskSuspendReq;
import jmash.protobuf.CustomEnumValue;
import jmash.protobuf.CustomEnumValueMap;
import jmash.protobuf.Entry;
import jmash.protobuf.EntryList;
import jmash.protobuf.EnumEntryReq;
import jmash.protobuf.EnumValueList;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Attachment;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.task.api.Task;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.flowable.variable.api.persistence.entity.VariableInstance;

/**
 * Grpc服务实现.
 */
@GrpcService
public class FlowImpl extends jmash.flow.FlowGrpc.FlowImplBase {

  private static Log log = LogFactory.getLog(FlowImpl.class);

  // 模块版本
  public static final String version = "v1.0.0";

  @Override
  public void version(Empty request, StreamObserver<StringValue> responseObserver) {
    responseObserver.onNext(StringValue.of(version + "-" + VersionUtil.snapshot(FlowImpl.class)));
    responseObserver.onCompleted();
  }

  @Override
  public void findEnumList(StringValue request, StreamObserver<EnumValueList> responseObserver) {
    try {
      List<EnumValue> list = ProtoEnumUtil.getEnumList(request.getValue());
      responseObserver.onNext(EnumValueList.newBuilder().addAllValues(list).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  public void findEnumMap(StringValue request,
      StreamObserver<CustomEnumValueMap> responseObserver) {
    try {
      Map<Integer, CustomEnumValue> values = ProtoEnumUtil.getEnumMap(request.getValue());
      responseObserver.onNext(CustomEnumValueMap.newBuilder().putAllValues(values).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  public void findEnumEntry(EnumEntryReq request, StreamObserver<EntryList> responseObserver) {
    try {
      List<Entry> entryList =
          ProtoEnumUtil.getEnumCodeList(request.getClassName(), request.getType());
      responseObserver.onNext(EntryList.newBuilder().addAllValues(entryList).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresPermissions("flow:proc_def:deploy")
  public void deployFlow(DeployReq request, StreamObserver<DeployRes> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      Deployment deployment = flowWrite.deployFlow(request);
      DeployRes deployRes = FlowMapper.INSTANCE.deployment(deployment);
      responseObserver.onNext(deployRes);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresPermissions("flow:proc_def:deploy")
  public void deployFlowXml(DeployXmlReq request, StreamObserver<DeployRes> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      Deployment deployment = flowWrite.deployFlowXml(request);
      DeployRes deployRes = FlowMapper.INSTANCE.deployment(deployment);
      responseObserver.onNext(deployRes);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresPermissions("flow:proc_def:delete")
  public void deleteDeployment(DeployKey request, StreamObserver<BoolValue> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      flowWrite.deleteDeployment(request.getDeploymentId());
      responseObserver.onNext(BoolValue.of(true));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresPermissions("flow:proc_def:list")
  public void findProcDefList(ProcDefReq request, StreamObserver<ProcDefList> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      List<ProcessDefinition> list = flowRead.findProcDefList(request);
      List<ProcDefModel> results = FlowMapper.INSTANCE.listProcDef(list);
      responseObserver.onNext(ProcDefList.newBuilder().addAllResults(results).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresPermissions("flow:proc_def:view")
  public void findProcDefById(ProcDefKey request, StreamObserver<ProcDefModel> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      ProcessDefinition entity = flowRead.findProcDefById(request.getProcDefId());
      ProcDefModel model = FlowMapper.INSTANCE.modelProcDef(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresPermissions("flow:proc_def:view")
  public void findProcDefXmlById(ProcDefKey request, StreamObserver<StringValue> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      String xml = flowRead.findProcDefXmlById(request.getProcDefId());
      responseObserver.onNext(StringValue.of(xml));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresPermissions("flow:proc_def:view")
  public void findProcDefDiagram(ProcDefKey request, StreamObserver<HttpBody> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      String realFileSrc = flowRead.findProcDefDiagram(request.getProcDefId());
      FileServiceUtil.downloadFile(responseObserver, realFileSrc);
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void startProcInst(StartProcInstReq request,
      StreamObserver<ProcInstModel> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      ProcessInstance inst = flowWrite.startProcInst(request);
      ProcInstModel model = FlowMapper.INSTANCE.modelProcInst(inst);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findMyTodoTaskPage(TaskReq request, StreamObserver<TaskPage> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      // 用户ID
      String userId = GrpcContext.USER_TOKEN.get().getName();
      log.info("查询用户Id为：" + userId + "的待办事项");
      TaskReq.Builder req = request.toBuilder();
      if (request.getCandidate()) {
        req.setCandidateUser(userId);
      } else {
        req.setAssigneeUser(userId);
      }
      TaskPage taskPage = flowRead.findTaskModelPage(req.build());
      responseObserver.onNext(taskPage);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findMyDoneProcInstPage(ProcInstReq request,
      StreamObserver<ProcInstPage> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      // 用户ID
      String userId = GrpcContext.USER_TOKEN.get().getName();
      ProcInstReq req = request.toBuilder().setInvolvedUser(userId).build();
      DtoPageImpl<ProcessInstance, DtoTotal> page = flowRead.findProcInstPage(req);
      ProcInstPage instPage = FlowMapper.INSTANCE.pageProcInst(page);
      responseObserver.onNext(instPage);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findMyFinishProcInstPage(HiProcInstReq request,
      StreamObserver<HiProcInstPage> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      // 用户ID
      String userId = GrpcContext.USER_TOKEN.get().getName();
      HiProcInstReq req = request.toBuilder().setInvolvedUser(userId).build();
      DtoPageImpl<HistoricProcessInstance, DtoTotal> page = flowRead.findHiProcInstPage(req);
      HiProcInstPage instPage = FlowMapper.INSTANCE.pageHiProcInst(page);
      responseObserver.onNext(instPage);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void claimTask(TaskClaimReq request, StreamObserver<Int32Value> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      int count = flowWrite.claimTask(request);
      responseObserver.onNext(Int32Value.of(count));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findTaskById(TaskKey request, StreamObserver<TaskModel> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      TaskModel model = flowRead.findTaskModelById(request.getTaskId());
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  @SuppressWarnings({"unchecked", "rawtypes"})
  public void findHiCommentList(ProcInstKey request,
      StreamObserver<HiCommentList> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      List<HiCommentModel> list = flowRead.findHiCommentList(request.getProcInstId());
      responseObserver.onNext(HiCommentList.newBuilder().addAllResults(list).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findProcInst(ProcInstKey request, StreamObserver<ProcInstModel> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      ProcessInstance procInst = flowRead.findProcInst(request.getProcInstId());
      ProcInstModel model = FlowMapper.INSTANCE.modelProcInst(procInst);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findProcInstVars(ProcInstKey request, StreamObserver<ProcInstVars> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      Map<String, Object> map = flowRead.findProcInstVars(request.getProcInstId());
      Map<String, Any> mapAny = FlowMapper.INSTANCE.toMapAny(map);
      responseObserver.onNext(ProcInstVars.newBuilder().putAllVars(mapAny).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findProcInstDiagram(ProcInstKey request, StreamObserver<HttpBody> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      String realFileSrc = flowRead.findProcInstDiagram(request.getProcInstId());
      FileServiceUtil.downloadFile(responseObserver, realFileSrc);
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void completeTask(TaskHandleReq request, StreamObserver<BoolValue> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      boolean result = flowWrite.completeTask(request);
      responseObserver.onNext(BoolValue.of(result));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findTaskDefAllowGoback(TaskKey request,
      StreamObserver<TaskDefList> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      TaskDefList list = flowRead.findTaskDefAllowGoback(request.getTaskId());
      responseObserver.onNext(list);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void gobackTask(TaskGobackReq request, StreamObserver<BoolValue> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      boolean result = flowWrite.gobackTask(request);
      responseObserver.onNext(BoolValue.of(result));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findTaskIdentityLink(TaskIdentityLinkReq request,
      StreamObserver<IdentityLinkList> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      List<IdentityLink> list = flowRead.findTaskIdentityLinkByReq(request);
      List<IdentityLinkModel> modelList = RuIdentitylinkMapper.INSTANCE.listTaskIdentityLink(list);
      responseObserver.onNext(IdentityLinkList.newBuilder().addAllResults(modelList).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findTaskAttachmentList(TaskAttachmentReq request,
      StreamObserver<TaskAttachmentList> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      List<Attachment> list = flowRead.findTaskAttachmentByReq(request);
      List<TaskAttachmentModel> modelList = TaskAttachmentMapper.INSTANCE.listTaskAttachment(list);
      responseObserver.onNext(TaskAttachmentList.newBuilder().addAllResults(modelList).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void createTaskAttachment(TaskAttachmentCreateReq request,
      StreamObserver<TaskAttachmentModel> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      Attachment entity = flowWrite.insertAttachment(request);
      TaskAttachmentModel model = TaskAttachmentMapper.INSTANCE.model(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void updateTaskAttachment(TaskAttachmentUpdateReq request,
      StreamObserver<TaskAttachmentModel> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      Attachment entity = flowWrite.updateAttachment(request);
      TaskAttachmentModel model = TaskAttachmentMapper.INSTANCE.model(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void deleteTaskAttachment(TaskAttachmentKey request,
      StreamObserver<TaskAttachmentModel> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      Attachment entity = flowWrite.deleteAttachment(request.getAttachmentId());
      TaskAttachmentModel model = TaskAttachmentMapper.INSTANCE.model(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void assignTask(TaskAssignReq request, StreamObserver<BoolValue> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      boolean result = flowWrite.assignTask(request);
      responseObserver.onNext(BoolValue.of(result));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void priorityTask(TaskPriorityReq request, StreamObserver<BoolValue> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      boolean result = flowWrite.priorityTask(request);
      responseObserver.onNext(BoolValue.of(result));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void delegateTask(TaskDelegateReq request, StreamObserver<BoolValue> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      boolean result = flowWrite.delegateTask(request);
      responseObserver.onNext(BoolValue.of(result));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void resolveTask(TaskResolveReq request, StreamObserver<BoolValue> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      boolean result = flowWrite.resolveTask(request);
      responseObserver.onNext(BoolValue.of(result));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void setBusinessStatus(BusinessStatusReq request,
      StreamObserver<BoolValue> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      boolean result = flowWrite.setBusinessStatus(request.getProcInstId(),
          request.getBusinessStatus());
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresPermissions("flow:monitor:list")
  public void findProcInstPage(ProcInstReq request, StreamObserver<ProcInstPage> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      DtoPageImpl<ProcessInstance, DtoTotal> page = flowRead.findProcInstPage(request);
      ProcInstPage instPage = FlowMapper.INSTANCE.pageProcInst(page);
      responseObserver.onNext(instPage);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresPermissions("flow:monitor:enable")
  public void suspendProcInst(ProcInstSuspendReq request,
      StreamObserver<BoolValue> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      boolean result = flowWrite.suspendProcInst(request);
      responseObserver.onNext(BoolValue.of(result));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresPermissions("flow:monitor:delete")
  public void deleteProcInst(ProcInstDeleteReq request,
      StreamObserver<BoolValue> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      boolean result = flowWrite.deleteProcInst(request);
      responseObserver.onNext(BoolValue.of(result));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findTaskPage(TaskReq request, StreamObserver<TaskPage> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      // 流程实例ID检查.
      if (StringUtils.isBlank(request.getProcInstId())) {
        throw new ParamsValidationException("procInstId", "流程实例ID不能为空!");
      }
      DtoPageImpl<Task, DtoTotal> page = flowRead.findTaskPage(request);
      TaskPage taskPage = FlowMapper.INSTANCE.pageTask(page);
      responseObserver.onNext(taskPage);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresPermissions("flow:monitor:enable")
  public void suspendTask(TaskSuspendReq request, StreamObserver<BoolValue> responseObserver) {
    try (FlowWrite flowWrite = FlowFactory.getFlowWrite(request.getTenant())) {
      boolean result = flowWrite.suspendTask(request);
      responseObserver.onNext(BoolValue.of(result));
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresPermissions("flow:hi_taskinst:list")
  public void findHiTaskinstList(HiTaskinstReq request,
      StreamObserver<HiTaskinstList> responseObserver) {
    try (HiTaskinstRead hiTaskinstRead = FlowFactory.getHiTaskinstRead(request.getTenant())) {
      List<HiTaskinstEntity> list = hiTaskinstRead.findListByReq(request);
      List<HiTaskinstModel> modelList = HiTaskinstMapper.INSTANCE.listHiTaskinst(list);
      responseObserver.onNext(HiTaskinstList.newBuilder().addAllResults(modelList).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findHiTaskinstById(HiTaskinstKey request,
      StreamObserver<HiTaskinstModel> responseObserver) {
    try (HiTaskinstRead hiTaskinstRead = FlowFactory.getHiTaskinstRead(request.getTenant())) {
      HiTaskinstEntity entity = hiTaskinstRead.findById(request.getId());
      HiTaskinstModel model = HiTaskinstMapper.INSTANCE.model(entity);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findHiProcInstById(HiProcinstKey request,
      StreamObserver<HiProcInstModel> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      HistoricProcessInstance procInst = flowRead.findHiProcInstById(request);
      HiProcInstModel model = FlowMapper.INSTANCE.modelHiProcInst(procInst);
      responseObserver.onNext(model);
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

  @Override
  @RequiresAuthentication
  public void findHiProcInstVars(ProcInstKey request,
      StreamObserver<ProcInstVars> responseObserver) {
    try (FlowRead flowRead = FlowFactory.getFlowRead(request.getTenant())) {
      Map<String, Object> map = flowRead.findHiProcVars(request.getProcInstId());
      Map<String, Any> mapAny = FlowMapper.INSTANCE.toMapAny(map);
      responseObserver.onNext(ProcInstVars.newBuilder().putAllVars(mapAny).build());
      responseObserver.onCompleted();
    } catch (Exception ex) {
      log.error("", ex);
      responseObserver.onError(Status.INTERNAL.withDescription(ex.getMessage()).asException());
    }
  }

}
